package com.toolbox.aspect;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.toolbox.annotation.TokenValidation;
import com.toolbox.bo.AccountBO;
import com.toolbox.exceptionhandler.DataException;
import com.toolbox.handler.AccountContext;
import com.toolbox.handler.RequestHandler;
import com.toolbox.service.JwtService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

import static com.toolbox.enums.ResponseStatusEnum.TOKEN_CAN_NOT_BE_EMPTY;
import static com.toolbox.enums.ResponseStatusEnum.TOKEN_PARSING_ERROR;

/**
 * <p>
 * Description：
 * </p>
 *
 * @author Mango
 * @version v1.0.0
 * @date 2023-11-20 16:00
 * @see com.toolbox.aspect
 */
@SuppressWarnings("ALL")
public class TokenValidationAspectHandler implements Ordered {

    private static final Logger log = LoggerFactory.getLogger(TokenValidationAspectHandler.class);

    /**
     * jwt 服务
     */
    @Autowired
    private JwtService jwtService;

    public Object aroundMethod(ProceedingJoinPoint pjp) {
        try {

            MethodSignature methodSignature = (MethodSignature) pjp.getSignature();

            log.info("aspect method: {} - {}", methodSignature.getDeclaringTypeName(), methodSignature.getName());

            // 获取注解
            TokenValidation annotation = getAnnotation(methodSignature);

            if (annotation == null && !annotation.validationType()) {
                Object proceed = pjp.proceed();
                return proceed;
            }

            // 获取当前request
            HttpServletRequest request = RequestHandler.getRequest();

            // 从当前request中获取token
            String token = request.getHeader(annotation.value());

            // 判断authorization是否为空
            if (StrUtil.isBlank(token)) {
                throw new DataException(TOKEN_CAN_NOT_BE_EMPTY.getMessage(), TOKEN_CAN_NOT_BE_EMPTY.getMessage());
            }

            // 使用token解析用户信息
            AccountBO bo = jwtService.parseToken(token);

            log.info("currently login user info: {}", JSON.toJSON(bo.toString()));

            if (!(null == bo)) {
                AccountContext.setUser(bo);
                Object proceed = pjp.proceed();
                return proceed;
            }

            throw new DataException(TOKEN_PARSING_ERROR.getMessage(), TOKEN_PARSING_ERROR.getMessage());

        } catch (Throwable throwable) {
            log.error("aroundMethod exception", throwable);
            throw new DataException(throwable.getMessage(), throwable.getMessage());
        } finally {
            AccountContext.clear();
        }
    }

    /**
     * 获取注解
     *
     * @param methodSignature 方法签名
     * @return 注解
     */
    private static TokenValidation getAnnotation(MethodSignature methodSignature) {
        Class<?> clazz = methodSignature.getDeclaringType();
        Method method = methodSignature.getMethod();
        TokenValidation annotation = (TokenValidation) method.getAnnotation(TokenValidation.class);
        if (annotation == null) {
            annotation = (TokenValidation) clazz.getAnnotation(TokenValidation.class);
        }
        return annotation;
    }

    @Override
    public int getOrder() {
        return -10000;
    }

}
